package com.luo.chengrui.module.sa.service.person;

import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.luo.chengrui.module.sa.controller.admin.org.vo.OrgCreateReqVO;
import com.luo.chengrui.module.sa.dal.dataobject.org.OrgDO;
import com.luo.chengrui.module.sa.dal.dataobject.person.PersonSyncDO;
import com.luo.chengrui.module.sa.dal.redis.RedisKeyConstants;
import com.luo.chengrui.module.sa.enums.GlobalStatusEnum;
import com.luo.chengrui.module.sa.enums.OrgKindEnum;
import com.luo.chengrui.module.sa.service.org.OrgAndPersonSyncService;
import com.luo.chengrui.module.sa.service.org.OrgService;
import com.luo.chengrui.module.sa.service.person.PersonService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;

import com.luo.chengrui.module.sa.controller.admin.person.vo.*;
import com.luo.chengrui.module.sa.dal.dataobject.person.PersonDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import com.luo.chengrui.module.sa.convert.person.PersonConvert;
import com.luo.chengrui.module.sa.dal.mysql.person.PersonMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.luo.chengrui.module.sa.enums.ErrorCodeConstants.*;;

/**
 * 人员  Service 实现类
 *
 * @author 诚睿
 */
@Service
@Validated
public class PersonServiceImpl implements PersonService {

    @Resource
    private PersonMapper personMapper;
    @Resource
    private OrgAndPersonSyncService orgAndPersonSyncService;
    @Resource
    private OrgService orgService;
    @Resource
    private PasswordEncoder passwordEncoder;

    private PersonServiceImpl getSelf() {
        return SpringUtil.getBean(getClass());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createPerson(PersonCreateReqVO createReqVO) {
        // 插入
        createReqVO.setVersion(System.currentTimeMillis());
        createReqVO.setPassword(passwordEncoder.encode(DEFAULT_PASSWORD));
        PersonDO person = PersonConvert.INSTANCE.convert(createReqVO);
        validatePersonCodeAndLoginNameUnique(null, createReqVO.getCode(), createReqVO.getLoginName());
        personMapper.insert(person);

        // 查询岗位
        OrgDO orgDO = orgService.getOrg(createReqVO.getMainOrgId());
        if (orgDO != null) {
            OrgCreateReqVO orgCreateReqVO = new OrgCreateReqVO();
            orgCreateReqVO.setId(person.getId() + "@" + createReqVO.getMainOrgId());
            orgCreateReqVO.setCode(createReqVO.getCode());
            orgCreateReqVO.setName(createReqVO.getName());
            orgCreateReqVO.setStatus(GlobalStatusEnum.ENABLED.getId());
            orgCreateReqVO.setLongName(createReqVO.getName());
            //0 不是虚拟组织，1 是虚拟组织
            orgCreateReqVO.setIsVirtual(GlobalStatusEnum.ENABLED.getId());
            orgCreateReqVO.setPersonId(person.getId());
            orgCreateReqVO.setOrgKindId(OrgKindEnum.Psm.getCode());
            orgCreateReqVO.setParentId(createReqVO.getMainOrgId());
            // 插入主岗位 psm 到sa_oporg表。
            orgService.createOrg(orgCreateReqVO);
        }
        orgAndPersonSyncService.personSync(person);

        // 返回
        return person.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePerson(PersonUpdateReqVO updateReqVO) {
        // 校验存在
        validatePersonExists(updateReqVO.getId());
        validatePersonCodeAndLoginNameUnique(updateReqVO.getId(), updateReqVO.getCode(), updateReqVO.getLoginName());
        // 更新
        PersonDO updateObj = PersonConvert.INSTANCE.convert(updateReqVO);
        personMapper.updateById(updateObj);
        PersonDO personDO = personMapper.selectById(updateObj.getId());
        orgAndPersonSyncService.personSync(personDO);
    }

    @Override
    public void repairMainOrgId(String personId, String mainOrgId) {
        PersonDO personDO = personMapper.selectById(personId);
        if (personDO == null) {
            throw exception(PERSON_NOT_EXISTS);
        }

        if (Objects.isNull(personDO.getMainOrgId())) {
            personMapper.updateById(new PersonDO().setId(personId).setMainOrgId(mainOrgId));
            orgAndPersonSyncService.personSync(personMapper.selectById(personId));
        } else {
            OrgDO psm = orgService.getOrg(personId + "@" + personDO.getMainOrgId());
            if (psm == null) {
                personMapper.updateById(new PersonDO().setId(personId).setMainOrgId(mainOrgId));
                orgAndPersonSyncService.personSync(personMapper.selectById(personId));
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePerson(String id) {
        // 校验存在
        PersonDO personDO = personMapper.selectById(id);
        if (personDO == null) {
            throw exception(PERSON_NOT_EXISTS);
        }
        // 删除
        personMapper.deleteById(id);
        if (!Objects.isNull(personDO.getSystemUserId())) {
            orgAndPersonSyncService.deletePerson(personDO.getSystemUserId());
        }
    }

    private void validatePersonExists(String id) {
        if (personMapper.selectById(id) == null) {
            throw exception(PERSON_NOT_EXISTS);
        }
    }

    private void validatePersonCodeAndLoginNameUnique(String id, String code, String loginName) {
        if (!Objects.isNull(code)) {
            PersonDO person = personMapper.selectOne(new PersonBaseVO().setCode(code));
            if (id == null && person != null) {
                throw exception(PERSON_CODE_EXISTS);
            }
            if (id != null && person != null && !Objects.equals(id, person.getId())) {
                throw exception(PERSON_CODE_EXISTS);

            }
        }
        if (!Objects.isNull(loginName)) {
            PersonDO person1 = personMapper.selectOne(new PersonBaseVO().setLoginName(loginName));
            if (id == null && person1 != null) {
                throw exception(PERSON_LOGIN_NAME_EXISTS);
            }
            if (id != null && person1 != null && !Objects.equals(id, person1.getId())) {
                throw exception(PERSON_LOGIN_NAME_EXISTS);
            }
        }
    }

    @Override
    public PersonDO getPerson(String id) {
        return personMapper.selectById(id);
    }

    @Override
    public PersonDO getPersonBySystemUserId(Long systemUserId) {
        PersonBaseVO reqVO = new PersonBaseVO();
        reqVO.setSystemUserId(systemUserId);
        return personMapper.selectOne(reqVO);
    }

    @Override
    @Cacheable(value = RedisKeyConstants.SA_PERSON_ALL_PSM_FULL_IDS, key = "#systemUserId")
    public List<String> getPersonFullIdsBySystemUserIdFromCache(Long systemUserId) {
        return personMapper.getPersonFullIdsBySystemUserId(systemUserId);
    }

    @Override
    public List<PersonDO> getPersonList(Collection<String> ids) {
        return personMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<PersonDO> getPersonPage(PersonPageReqVO pageReqVO) {
        return personMapper.selectPage(pageReqVO);
    }

    @Override
    public List<PersonDO> getPersonList(PersonExportReqVO exportReqVO) {
        return personMapper.selectList(exportReqVO);
    }

    @Override
    public List<PersonSyncDO> getSyncPersonList() {
        return personMapper.selectSyncList();
    }

    @Override
    public PersonInfoVO getLoginPersonInfo() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        PersonDO personDO = getSelf().getPersonBySystemUserId(loginUser.getId());
        List<OrgDO> orgDOList = orgService.getPsmListBySystemUserId(loginUser.getId());
        PersonInfoVO personInfoVO = new PersonInfoVO();
        personInfoVO.setPersonInfo(personDO);
        personInfoVO.setOrgInfo(orgDOList);
        return personInfoVO;
    }

    @Override
    public PersonInfoVO getPersonInfo(String personId) {
        PersonDO personDO = getSelf().getPerson(personId);
        List<OrgDO> orgDOList = orgService.getPsmListById(personId);
        PersonInfoVO personInfoVO = new PersonInfoVO();
        personInfoVO.setPersonInfo(personDO);
        personInfoVO.setOrgInfo(orgDOList);
        return personInfoVO;
    }
}
